<?php

/*
 * Фронт-контроллер.
 * Определяет приложение.
 * Запускает роутер, чтобы тот разобрал URL.
 * На основании данных от роутера определяет контроллер и действие.
 * Передает им управление.
 */

namespace T4;

use T4\Debug;

class FrontController {

	/**
	 *
	 * @var T4\Application Ссылка на приложение, определенное фронт-контроллером 
	 */
	public static $application;

	/**
	 *
	 * @var T4\Theme Ссылка на тему сайта, с которой работает фронт-контроллер
	 */
	public static $theme;

	/**
	 * Основной метод
	 */
	public static function execute() {

                /**
		 * Пытаемся определить имя приложения
		 * И если получилось - создать объект этого приложения
		 */
		$application = Application::detectName();

		if (!Application::exists($application)) {
			throw new Exception('Приложение ' . $application . ' не существует');
		};

		/**
		 * Тему надо создать пораньше, иначе она не попадет в Application::getView()
		 */
		if (!self::isCLI()) {
			$themeClass = '\\THEMES\\' . ucfirst(CMS::getCurrentTheme());
			$theme = self::$theme = new $themeClass;
		}

		self::$application = $application = Application::getInstance($application);

		/**
		 * Берем у приложения конфигурацию роутинга
		 * Передаем ее и URI роутеру
		 * Получаем результат
		 * 
		 * @todo $_GET['__URI'] может быть пустая и сейчас имеем Undefined index: __URI
		 */
		$routerResult = Router::execute(
			isset($_GET['__URI']) ? $_GET['__URI'] : '', 
			$application->routing
		);

		if (empty($routerResult->controller) && empty($routerResult->action)) {
			throw new Exception('Роутер не смог найти путь');
		}

		/**
		 * Вызов действия контроллера
		 */
                if (DEBUG)
			Debug::timerBegin();
		
                $result = self::call($application->name, $routerResult->controller, $routerResult->action, $routerResult->parameters);

                if (DEBUG)
			Debug::logCall($application->name, $routerResult->controller, $routerResult->action, Debug::timerEnd());
		
		/**
		 * Выводим результат
		 * Если не cli-режим, то заодно выведем заголовок с кодировкой
		 * Важно еще учесть, что у приложения admin - свой шаблон в теме
		 */
                
                if ( self::isCLI() ) {
                    echo $result;
                } else {
                    if ( 'admin' == $application->name ) {
                        header('Content-type: text/html; charset=UTF-8');
                        echo $result;
                    }
                    elseif ( empty($routerResult->output) || 'HTML' == $routerResult->output ) {
                       $output = new OUTPUT\HTML($application->path . '/templates/' . ucfirst($routerResult->controller) . '/' . $routerResult->action . '.html');
                       $theme->assign('CONTENT', $output->prepare($result));
                       header('Content-type: text/html; charset=UTF-8');
                       echo $theme->render();
                    }
                }
                return;
		
	}

	/**
	 * Вызов заданного действия контроллера приложения
	 * @param string $applicationName Имя приложения
	 * @param string $controllerName Имя контроллера
	 * @param string $actionName Имя действия
         * @param T4\Standard $parameters Параметры
	 * @return T4\Standard Результат исполнения
	 */
	public static function call($applicationName, $controllerName, $actionName, $parameters = null) {

		if (!Application::exists($applicationName)) {
			throw new Exception('Приложение ' . $applicationName . ' не существует');
		};

		$application = Application::getInstance($applicationName);
		$controllerClass = $application->namespace . '\\CONTROLLERS\\' . $controllerName;

		if (!class_exists($controllerClass, true)) {
			throw new Exception('Не найден класс контроллера');
		}

		/**
		 * Создаем объект контроллера, устанавливаем ему параметры
		 */
		$controller = new $controllerClass;
		if (!is_null($parameters))
			$controller->parameters = $parameters;
		/**
		 * Вызов действия и получение результата
		 */
		
		if ( DEBUG )
			Debug::timerBegin();

		$result = $controller->action($actionName);

		if ( DEBUG )
			Debug::logCall($application->name, $controllerName, $actionName, Debug::timerEnd());
		
		return $result;
		
	}

	/**
	 * 
	 * @return boolean Работает ли сайт в cli-режиме?
	 */
	protected static function isCLI() {
		return !isset($_SERVER['HTTP_HOST']);
	}

}